package com.example.demofdfs.test2;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ConcurrentHashMapTest {

	static ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(10);
	
//	public static void main(String[] args) {
//		test();
//		
//		
//	}
	
	private static List<Thread> runnables = new ArrayList<>();

	private static void test() {
//		Map<String, Integer> map = new ConcurrentHashMap<>();
		Map<String, Integer> map = new HashMap<>();
//		map.put("a", 1);
//		map.put("b", 1);
//		map.put("c", 1);
//		map.put("d", 1);
		
//		threadPoolExecutor.execute(runnable(map));
//		threadPoolExecutor.execute(runnable2(map));
//		new Thread(foreach(map)).start();
//		new Thread(put(map)).start();
//		new Thread(remove(map)).start();
		
		runnables.add(new Thread(foreach(map), "foreach"));
		runnables.add(new Thread(put(map)));
		runnables.add(new Thread(remove(map)));
		
		runnables.forEach(new Consumer<Thread>() {
			@Override
			public void accept(Thread t) {
				t.start();
			}
		});

		while (true) {
			for (Iterator<Thread> it = runnables.iterator(); it.hasNext(); ) {
				Thread t = it.next();
				if (! t.isAlive()) {
					System.out.println(t.getName() + ">>>>>>>>>>>>>");
					flag = true;
				}
				if (flag) {
//					t.interrupt();
					it.remove();
				}
			}
			if (runnables.isEmpty())
				break;
			
		}
		System.out.println(map);
	}
	
	public static Runnable foreach(Map<String, Integer> map) {
		return ()->{
			while (true) {
				map.forEach(new BiConsumer<String, Integer>() {
					@Override
					public void accept(String t, Integer u) {
						System.out.println(t + " = " + u);
					} 
				});
				sleep(100L);
				System.out.println(map);
			}
		};
	}
	public static Runnable put(Map<String, Integer> map) {
		return ()->{
			while (true) {
				if (flag) {
					break;
				}
				map.put(key(), 2);
				sleep(100L);
			}
		};
	}
	
	public static Runnable remove(Map<String, Integer> map) {
		return ()->{
			if (queue == null) {
				queue = new ArrayDeque<>();
			}
			while (true) {
				if (flag) {
					break;
				}
				map.remove(queue.poll());
				sleep(100L);
			}
		};
	}
	
	private static String key;
	private static volatile Queue<String> queue = new ArrayDeque<>();
	private static boolean flag = false;
	
	public static String key() {
		if (queue == null) {
			queue = new ArrayDeque<>();
		}
		key = UUID.randomUUID().toString();
		queue.offer(key);
		return key;
	}
	
	public static void sleep(long l) {
		try {
			Thread.sleep(l);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
